package com.lichongbing.lyoggl.controller;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.cache.Cache;
import com.lichongbing.lyoggl.annotation.AccessLimit;
import com.lichongbing.lyoggl.exception.AppleIDResponseCodeEnum;
import com.lichongbing.lyoggl.exception.SignInWithAppleException;
import com.lichongbing.lyoggl.model.AppleIDResDTO;
import com.lichongbing.lyoggl.model.AppleIDValidateInfo;
import com.lichongbing.lyoggl.model.TimeLine;
import com.lichongbing.lyoggl.service.TimeLineService;

import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.apache.commons.codec.binary.Base64;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.Map;
import java.util.UUID;

/**
 * @author lichongbing
 * @version 1.0.0
 * @createdate 2021/12/19 8:30 下午
 * @description: TODO
 */
@Slf4j
@RestController
@RequestMapping("/timeline")
public class TimeLineController {

    @Autowired
    private TimeLineService timeLineService;

    @Autowired
    private Cache<String, String> cache;

    @Autowired
    private RestTemplate restTemplate;

    @Value("${appleIDValidateURL}")
    private String appleIDValidateURL;

    @Value("${appleIDPublicKeyURL}")
    private String appleIDPublicKeyURL;

    @Value("${redirectURI}")
    private String redirectURI;

    @Value("${kid}")
    private String kid;

    @Value("${iss}")
    private String iss;

    @Value("${privateKey}")
    private String privateKey;


    @Value("${expSeconds}")
    private String expSeconds;

    @Value("${ISS_FIELD}")
    private String ISS_FIELD;


    @Value("${PRIVATEKEY_ALGORITHM_EC}")
    private String PRIVATEKEY_ALGORITHM_EC;

    @Value("${clientID}")
    private String clientID;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @PostMapping("add")
    public String createtimeline(@RequestBody JSONObject jsonObject) {
        String id = UUID.randomUUID().toString().replace("-", "");
        TimeLine oldtimeLine = timeLineService.findByCurent();
        String oldstart = oldtimeLine.getStart();
        String name = jsonObject.getString("name");
        String start = jsonObject.getString("start");
        String descriptions = jsonObject.getString("descriptions");
        String tags = jsonObject.getString("tags");
        long duration = getDuration(oldstart, start);
        if (oldtimeLine == null) {
            TimeLine timeline = new TimeLine();
            timeline.setId(id);
            timeline.setName(name);
            timeline.setStart(start);
            timeline.setDescriptions(descriptions);
            timeline.setTags(tags);
            timeline.setState("1");
            boolean save = timeLineService.save(timeline);
            // int insert = timeLineService.insert(timeline);
            return "结果" + save;
        } else {
            TimeLine timeline = new TimeLine();
            timeline.setId(id);
            timeline.setName(name);
            timeline.setStart(start);
            timeline.setDescriptions(descriptions);
            timeline.setTags(tags);
            timeline.setState("1");
            oldtimeLine.setState("0");
            oldtimeLine.setStop(start);
            oldtimeLine.setDuration((double) duration);
            timeLineService.updateById(oldtimeLine);
            boolean save = timeLineService.save(timeline);
            // int insert = timeLineService.insert(timeline);
            return "结果" + save;
        }

    }

    /**
     * @author lichongbing
     * @update 2022/2/15 1:56 下午
     * @description: 新增计时器
     */

    private long getDuration(String oldstart, String start) {
        DateTime oldTime = DateUtil.parse(oldstart);
        DateTime newTime = DateUtil.parse(start);
        long betweenMinutes = DateUtil.between(oldTime, newTime, DateUnit.MINUTE);
        return betweenMinutes;
    }
    @PostMapping("adds")
    public String createtimelineBygoogle(@RequestParam("name") String name,
                                         @RequestParam("start") String start,
                                         @RequestParam("descriptions") String descriptions,
                                         @RequestParam("tags") String tags
    ) {
        String id = UUID.randomUUID().toString().replace("-", "");
        TimeLine oldtimeLine = timeLineService.findByCurent();
        if (oldtimeLine == null) {
            TimeLine timeline = new TimeLine();
            timeline.setId(id);
            timeline.setName(name);
            timeline.setStart(start);
            timeline.setDescriptions(descriptions);
            timeline.setTags(tags);
            timeline.setState("1");
            boolean save = timeLineService.save(timeline);
            return "结果" + save;
        } else {
            TimeLine timeline = new TimeLine();
            timeline.setId(id);
            timeline.setName(name);
            timeline.setStart(start);
            timeline.setDescriptions(descriptions);
            timeline.setTags(tags);
            timeline.setState("1");
            oldtimeLine.setState("0");
            oldtimeLine.setStop(start);
            boolean save = timeLineService.save(timeline);
            if (save) {
                timeLineService.updateById(oldtimeLine);
            }
            return "结果" + save;
        }
    }

    @AccessLimit(seconds = 1, maxcount = 1, needLogin = false)
    @PostMapping("addtime")
    public void addTime(@RequestBody JSONObject jsonObject) {
        String id = UUID.randomUUID().toString().replace("-", "");
        String name = jsonObject.getString("name");
        String start = jsonObject.getString("start");
        String descriptions = jsonObject.getString("descriptions");
        String tags = jsonObject.getString("tags");
        TimeLine timeline = new TimeLine();
        timeline.setId(id);
        timeline.setName(name);
        timeline.setStart(start);
        timeline.setDescriptions(descriptions);
        timeline.setTags(tags);
        timeline.setState("1");
        ValueOperations<String, String> stringStringValueOperations = redisTemplate.opsForValue();
        String oldoutid = stringStringValueOperations.get("tid");
        timeLineService.addtime(timeline, oldoutid);
        ValueOperations<String, String> stringStringValueOperations1 = redisTemplate.opsForValue();
        stringStringValueOperations1.set("tid", id);
    }

    /**
     * route print
     * route delete 0.0.0.0 mask 0.0.0.0 192.168.32.254
     * route add 192.168.0.0 mask 255.255.255.0 192.168.32.254
     */

    @PostMapping("applelogin")
    public String applelogin(@RequestBody JSONObject jsonObject) {
        //获取apple的用户唯一标识
        String user = jsonObject.getString("user");
        //authorizationCode传递给苹果服务做校验 5分钟有效
        String authorizationCode = jsonObject.getString("authorizationCode");
        //获取apple的identityToken 10 分钟有效
        String identityToken = jsonObject.getString("identityToken");
        //解码 apple的identityToken
        identityToken = new String(Base64.decodeBase64(identityToken));
        //验证客户端identityToken请求
        Boolean isok = this.checkIdentityToken(identityToken);


        //通过Apple服务验证用户,缺乏私钥证书，没有后续操作。
        /*
        AppleIDValidateInfo appleIDValidateInfo = new AppleIDValidateInfo();
        appleIDValidateInfo.setGrant_type("authorization_code");
        appleIDValidateInfo.setCode(authorizationCode);
        appleIDValidateInfo.setRedirect_uri(redirectURI);
        appleIDValidateInfo.setClient_id(aud);
        appleIDValidateInfo.setClient_secret(this.buildClientSecret(aud));
        AppleIDResDTO appleIDResDTO = validateAppleIDTokens(appleIDValidateInfo);
        try {
            checkResultInfo(appleIDResDTO);
        }catch(Exception e) {
            e.printStackTrace();
        }

         */
        return null;
    }

    private String ggg() {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Accept", "application/json");
        headers.add("Content-Type", "application/json;charset=UTF-8");

        return null;
    }

    @PostMapping("applelogins")
    public String applelogins() {
        String identityToken = "ZXlKcmFXUWlPaUptYURaQ2N6aERJaXdpWVd4bklqb2lVbE15TlRZaWZRLmV5SnBjM01pT2lKb2RIUndjem92TDJGd2NHeGxhV1F1WVhCd2JHVXVZMjl0SWl3aVlYVmtJam9pWTI5dExteHBZMmh2Ym1kaWFXNW5MbXg1YjJkbmJHRndjQ0lzSW1WNGNDSTZNVFkwT0Rnek1UVTRNeXdpYVdGMElqb3hOalE0TnpRMU1UZ3pMQ0p6ZFdJaU9pSXdNREExTlRFdU1EWTJZemsxTjJNME9XVXhOR0V4WVdGak5tRm1NMkZsTmpKaU0yRTNOemt1TURreE9DSXNJbU5mYUdGemFDSTZJbU5HY25walZVRnNVVWR2ZW5kNU16SnVSMll0TldjaUxDSmxiV0ZwYkNJNklqZzJOVEUwTXpFMU1rQnhjUzVqYjIwaUxDSmxiV0ZwYkY5MlpYSnBabWxsWkNJNkluUnlkV1VpTENKaGRYUm9YM1JwYldVaU9qRTJORGczTkRVeE9ETXNJbTV2Ym1ObFgzTjFjSEJ2Y25SbFpDSTZkSEoxWlgwLkp1aTRoSWVWMVJxSFJYci1HSmR2cUVxcmFRa3FpY1otMVNab2taanN0N2NXM1hmcnJSYzJIWU5aMUdaUWgyeVNoc0RyZ3RaSE9oZzFiby0yQnM5M2lnZVQ0TWxheDFQVmZYNEtQZEpwbWwyQnVfT3lGMzkwRWw1V0QwTEYyaEZWckNWVU5kbEthUGpscC03VlM5TEtUQzNEYzc1OWFsZUxuaGxwOG1QYUE5dXFMNnZxSERCYzhqTDVxaFhYQlNpYnBSLTZybTRpS1lrUEJUQnFXakQwenVpOHJpbWU3Zm9CRm12ZmxMcHZYc0N3WWxjSmJ2ekp3Q0MxNTNNdjh3SmVWWnpxVnA3OUdCdXdoZF9IcHJOTGlNMmEybWpmTUNwdzNQR0JSY1gxRHZFLW5lUGZRVzZsUFRxYU5HaktQSXJhbDN1VV9iT3d2WEZ2MU1BT3JhSTFFZw==";
        identityToken = new String(Base64.decodeBase64(identityToken));
        try {
            String firstDate = new String(Base64.decodeBase64(identityToken.split("\\.")[0]), "UTF-8");
            System.out.println(firstDate);
            String claim = new String(Base64.decodeBase64(identityToken.split("\\.")[1]), "UTF-8");
            String kid = JSONObject.parseObject(firstDate).get("kid").toString();
            String e = getApplePublicKey(kid).getString("e");
            String n = getApplePublicKey(kid).getString("n");
            String kty = getApplePublicKey(kid).getString("kty");
            String aud = JSONObject.parseObject(claim).get("aud").toString();
            String sub = JSONObject.parseObject(claim).get("sub").toString();
            BigInteger modulus = new BigInteger(1, Base64.decodeBase64(n));
            BigInteger publicExponent = new BigInteger(1, Base64.decodeBase64(e));
            RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, publicExponent);
            KeyFactory kf = KeyFactory.getInstance(kty);
            PublicKey publicKey = kf.generatePublic(spec);
            JwtParser jwtParser = Jwts.parser().setSigningKey(publicKey);
            jwtParser.requireIssuer("https://appleid.apple.com");
            jwtParser.requireAudience(aud);
            jwtParser.requireSubject(sub);
            boolean result = false;
            Jws<Claims> claims = jwtParser.parseClaimsJws(identityToken);
            if (claims != null && claims.getBody().containsKey("auth_time")) {
                result = true;
            }
        } catch (Exception e) {
            System.out.println(e);
        }
        return null;
    }

    @PostMapping("day")
    public String getweeks() {


        String data = "{\n" +
                "  \"day0\":  [\n" +
                "    {  \"id\": \"1\",\n" +
                "      \"title\": \"睡觉\",\n" +
                "      \"color\": \"orange\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    },\n" +
                "    {\n" +
                "      \"id\": \"2\",\n" +
                "      \"title\": \"吃饭\",\n" +
                "      \"color\": \"yellow\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    },\n" +
                "    {\n" +
                "      \"id\": \"3\",\n" +
                "      \"title\": \"上班\",\n" +
                "      \"color\": \"green\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    }\n" +
                "  ],\n" +
                "  \"day1\":  [\n" +
                "    {\n" +
                "      \"id\": \"4\",\n" +
                "      \"title\": \"睡觉\",\n" +
                "      \"color\": \"orange\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    },\n" +
                "    {\"id\": \"5\",\n" +
                "      \"title\": \"吃饭\",\n" +
                "      \"color\": \"yellow\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    },\n" +
                "    {\"id\": \"6\",\n" +
                "      \"title\": \"上班\",\n" +
                "      \"color\": \"green\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    }\n" +
                "  ],\n" +
                "  \"day2\":  [\n" +
                "    {\"id\": \"7\",\n" +
                "      \"title\": \"睡觉\",\n" +
                "      \"color\": \"orange\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    },\n" +
                "    {\"id\": \"8\",\n" +
                "      \"title\": \"吃饭\",\n" +
                "      \"color\": \"yellow\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    },\n" +
                "    {\n" +
                "      \"id\": \"9\",\n" +
                "      \"title\": \"上班\",\n" +
                "      \"color\": \"green\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    }\n" +
                "  ],\n" +
                "  \"day3\":  [\n" +
                "    {\n" +
                "      \"id\": \"10\",\n" +
                "      \"title\": \"睡觉\",\n" +
                "      \"color\": \"orange\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    },\n" +
                "    {\n" +
                "      \"id\": \"11\",\n" +
                "      \"title\": \"吃饭\",\n" +
                "      \"color\": \"yellow\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    },\n" +
                "    {\n" +
                "      \"id\": \"12\",\n" +
                "      \"title\": \"上班\",\n" +
                "      \"color\": \"green\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    }\n" +
                "  ],\n" +
                "  \"day4\":  [\n" +
                "    {\"id\": \"13\",\n" +
                "      \"title\": \"睡觉\",\n" +
                "      \"color\": \"orange\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    },\n" +
                "    {\n" +
                "      \"id\": \"14\",\n" +
                "      \"title\": \"吃饭\",\n" +
                "      \"color\": \"yellow\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    },\n" +
                "    {\n" +
                "      \"id\": \"15\",\n" +
                "      \"title\": \"上班\",\n" +
                "      \"color\": \"green\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    }\n" +
                "  ],\n" +
                "  \"day5\":  [\n" +
                "    {\n" +
                "      \"id\": \"16\",\n" +
                "      \"title\": \"睡觉\",\n" +
                "      \"color\": \"orange\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    },\n" +
                "    {\"id\": \"17\",\n" +
                "      \"title\": \"吃饭\",\n" +
                "      \"color\": \"yellow\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    },\n" +
                "    {\n" +
                "      \"id\": \"18\",\n" +
                "      \"title\": \"上班\",\n" +
                "      \"color\": \"green\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    }\n" +
                "  ],\n" +
                "  \"day6\":  [\n" +
                "    {\n" +
                "      \"id\": \"19\",\n" +
                "      \"title\": \"睡觉\",\n" +
                "      \"color\": \"orange\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    },\n" +
                "    {\n" +
                "      \"id\": \"20\",\n" +
                "      \"title\": \"吃饭\",\n" +
                "      \"color\": \"yellow\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    },\n" +
                "    {\n" +
                "      \"id\": \"21\",\n" +
                "      \"title\": \"上班\",\n" +
                "      \"color\": \"green\",\n" +
                "      \"height\": \"240.0\",\n" +
                "      \"date\": \"20\"\n" +
                "    }\n" +
                "  ],\n" +
                "  \"month\":  \"3\",\n" +
                "  \"year\":  \"2022\",\n" +
                "  \"today\": \"28\",\n" +
                "  \"week\": \"0\"\n" +
                "}";


        return data;
    }

    @PostMapping("savecache")
    public void saveCache(@RequestBody JSONObject jsonObject) {
        String key = jsonObject.getString("key");
        String value = jsonObject.getString("value");
        cache.put(key, value);
    }

    @PostMapping("getcache/{key}")
    public String getCache(@PathVariable String key) {
        String ifPresent = cache.getIfPresent(key);
        return ifPresent;
    }

    @Scheduled(fixedDelay = (long) (2 * 500 * 1000))
    @Scheduled(cron = "0 0 2 * * ?")
    @PostMapping("cacheApplePublicKey")
    public void cacheApplePublicKeys() {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Accept", "application/json");
        HttpEntity<String> http = new HttpEntity("", headers);
        ResponseEntity<String> responseEntity = restTemplate.exchange(appleIDPublicKeyURL, HttpMethod.GET, http, String.class);
        String body = responseEntity.getBody();
        JSONObject jsonObject = JSONObject.parseObject(body);
        JSONArray keys = jsonObject.getJSONArray("keys");
        String keyJsonStr = keys.toJSONString();
        cache.put("keys", keyJsonStr);
    }
    //验证客户端identityToken请求
    private Boolean checkIdentityToken(String identityToken) {
        boolean result = false;
        try {
            //分段切割获取数据
            String firstDate = new String(Base64.decodeBase64(identityToken.split("\\.")[0]), "UTF-8");
            System.out.println(firstDate);
            //第二段数据
            String claim = new String(Base64.decodeBase64(identityToken.split("\\.")[1]), "UTF-8");
            // 获取aud
            String aud = JSONObject.parseObject(claim).get("aud").toString();
            // 获取sub
            String sub = JSONObject.parseObject(claim).get("sub").toString();
            // 获取 email
            String email = JSONObject.parseObject(claim).get("email").toString();
            // 获取iss
            String iss = JSONObject.parseObject(claim).get("iss").toString();
            // 获取kid
            String kid = JSONObject.parseObject(firstDate).get("kid").toString();
            //通过kid 获取 apple 公钥
            PublicKey publicKey = processPublicKey(kid);
            // 通过 apple 的公钥 解密签名
            JwtParser jwtParser = Jwts.parser().setSigningKey(publicKey);
            jwtParser.requireIssuer(iss);
            jwtParser.requireAudience(aud);
            jwtParser.requireSubject(sub);
            //验证客户端请求
            Jws<Claims> claims = jwtParser.parseClaimsJws(identityToken);
            if (claims != null && claims.getBody().containsKey("auth_time")) {
                result = true;
            }
        } catch (Exception e) {
            System.out.println(e);
        }
        return result;
    }


    @PostMapping("getApplePublicKey/{kid}")
    private JSONObject getApplePublicKey(@PathVariable String kid) {
        String ifPresent = cache.getIfPresent("keys");
        JSONArray jsonArray = JSONArray.parseArray(ifPresent);
        String kidValue = null;
        JSONObject jsonObject = null;
        int i = 0;
        while (!kid.equals(kidValue)) {
            jsonObject = jsonArray.getJSONObject(i);
            kidValue = jsonObject.getString("kid");
            i++;
        }

        return jsonObject;
    }

    /**
     * 校验返回值
     * 非空/有值校验
     *
     * @param appleIDResDTO
     */
    private void checkResultInfo(AppleIDResDTO appleIDResDTO) {
        Assert.notNull(appleIDResDTO, "AppleID validateAppleIDTokens return null!");
        if (StringUtils.isNotBlank(appleIDResDTO.getError()) || StringUtils.isBlank(appleIDResDTO.getId_token())) {
            String errorMsg = appleIDResDTO.getError();
            log.error("AppleID validateAppleIDTokens has error msg:{}", errorMsg);
            throw new SignInWithAppleException(AppleIDResponseCodeEnum.BAD_RESPONSE);
        }
    }

    /**
     * 访问Apple服务验证用户信息
     *
     * @param validateInfo
     * @return
     */
    public AppleIDResDTO validateAppleIDTokens(AppleIDValidateInfo validateInfo) {
        AppleIDResDTO appleIDResDTO = new AppleIDResDTO();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
        params.add("client_id", validateInfo.getClient_id());
        params.add("client_secret", validateInfo.getClient_secret());
        params.add("code", validateInfo.getCode());
        params.add("grant_type", validateInfo.getGrant_type());
        params.add("redirect_uri", validateInfo.getRedirect_uri());
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(params, headers);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(appleIDValidateURL, requestEntity, String.class);
        String body = responseEntity.getBody();
        AppleIDResDTO appleIDResDTOs = JSON.parseObject(body, AppleIDResDTO.class);
        return appleIDResDTOs;
    }

    /**
     * 构建client_secret JWT格式 暂时不用
     *
     * @param clientId
     * @return
     */
    private String buildClientSecret(String clientId) {
        //heander
        Map<String, Object> header = Jwts.header();
        header.put("alg", "ES256");
        header.put("kid", kid);
        //荷载
        Map<String, Object> claims = Jwts.claims();
        long now = System.currentTimeMillis() / 1000;
        claims.put("iss", iss);
        claims.put("iat", now);
        claims.put("exp", now + expSeconds);
        claims.put("aud", ISS_FIELD);//固定
        claims.put("sub", clientId);//注意！这里是IdentityToken获取到的client_id
        //通过JWT加密生成
        return Jwts.builder()
                .setHeader(header)
                .setClaims(claims)
                .signWith(SignatureAlgorithm.ES256, this.processPrivateKey(privateKey))
                .compact();
    }

    /**
     * 加工私钥 暂时不用
     *
     * @param sourceKey
     * @return
     */
    private PrivateKey processPrivateKey(String sourceKey) {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(sourceKey));
        PrivateKey privateKey = null;
        KeyFactory keyFactory = null;
        try {
            keyFactory = KeyFactory.getInstance(PRIVATEKEY_ALGORITHM_EC);
            privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        } catch (NoSuchAlgorithmException e) {
            log.error("AppleID processPrivateKey NoSuchAlgorithmException e:{}", e.getMessage());
        } catch (InvalidKeySpecException e) {
            log.error("AppleID processPrivateKey InvalidKeySpecException e:{}", e.getMessage());
        }
        Assert.notNull(privateKey, "AppleID processPrivateKey privateKey is null");
        return privateKey;

    }

    /**
     * 获取apple公钥
     *
     * @param kid
     * @return PublicKey
     */
    private PublicKey processPublicKey(String kid) {
        String exponent = getApplePublicKey(kid).getString("e");
        String modulus = getApplePublicKey(kid).getString("n");
        String kty = getApplePublicKey(kid).getString("kty");
        Assert.hasLength(exponent, "publicKey中e值为空");
        Assert.hasLength(modulus, "publicKey中n值为空");
        RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(
                new BigInteger(1, Base64.decodeBase64(modulus)),
                new BigInteger(1, Base64.decodeBase64(exponent)));
        KeyFactory keyFactory = null;
        PublicKey fianlKey = null;
        try {
            keyFactory = KeyFactory.getInstance(kty);
            fianlKey = keyFactory.generatePublic(rsaPublicKeySpec);
        } catch (NoSuchAlgorithmException e) {
            log.error("AppleID processPublicKey NoSuchAlgorithmException{}", e.getMessage());
        } catch (InvalidKeySpecException e) {
            log.error("AppleID processPublicKey InvalidKeySpecException{}", e.getMessage());
        }
        Assert.notNull(fianlKey, "AppleID processPublicKey pulicKey is null");
        return fianlKey;
    }
}
